#ifndef PHYSICS_LOGIC_H
#define PHYSICS_LOGIC_H

#include "WindowsCompatibility/Physx.h"
#include "Util/PerformanceTest.h"
#include "PhysxPicking.h"
#include "WrappedContainers/ArrayList.h"
#include "Entities/Skybox.h"
#include "Entities/Flag.h"
#include "Camera.h"

#include "Entities/ActorEntities/CannonBall.h"

struct Light;
class Camera;
class DebugRenderer;
class Flag;
class CannonBall;

class PhysicsLogic {
protected:
	enum SELECTABLE_HUD_ELEMENT {
		SHE_NONE,
		SHE_TOWER,
		SHE_WALL_FRONT,
		SHE_WALL_SIDE,
		SHE_HOUSE,
		SHE_CANNON_BALL_NORMAL,
		SHE_CANNON_BALL_EXPLOSIVE,
		SHE_END_TURN,
		SHE_BUILD_OR_ATTACK,
		SHE_SHOOT,
		SHE_PLACE,
		SHE_CLEAR,
		SHE_RESET_GAME,
        SHE_TOGGLE_CAM,

		SELECTABLE_HUD_ELEMENTS_COUNT
	};

protected:
	static NxPhysicsSDK* physicsSDK;
	static NxScene*	scene;

	static Light sunLight;

	static Camera camera;
	static Camera hudCamera;

	static NxVec3 cameraVelocity;
	static NxVec3 cameraBounds;

	static CannonBall* observedCannonBall;
	static bool cannonBallCameraEnabled;
	static bool cameraLocked;

	static Skybox* skybox;

	static PerformanceTest pt;
	static DebugRenderer debugRenderer;

	static NxVec3 wind;

	static const float flagViewW;
	static const float flagViewH;

	static float hudMessageTimeToLive;
	static const float hudMessageMaxTimeToLive;
	static std::string hudMessage;

	static int lastClickGlTime;
	static int lastClickX;
	static int lastClickY;
	static int mouseButtonState[3];
	static int lastMousePosX;
	static int lastMousePosY;

public:
	static SurfaceRenderingData textMaterial;
	static SurfaceRenderingData textShadowMaterial;
	static SurfaceRenderingData helpPanelMaterial;
	static SurfaceRenderingData buttonMaterial;
	static SurfaceRenderingData namePanelMaterial;
	static SurfaceRenderingData bottomPanelMaterial;
	static SurfaceRenderingData flagPanelMaterial;
	static SurfaceRenderingData flagPanelMaterial2;
    static SurfaceRenderingData buttonFreeCamMaterial;
    static SurfaceRenderingData buttonFixedCamMaterial;

public:
	static bool Init();
	static void Exit();

	static bool IsHardwareAccelerationSupported();

	static NxVec3 GetCameraForward();

	static inline NxScene* GetScene() { return scene; }
	static inline NxPhysicsSDK* GetPhysicsSDK() { return physicsSDK; }

	static void ClearScene();

	static void MakeCCD(NxShape* shape);

	static void CreateGround();

	static void CreateBrick(const NxVec3& pos, const NxVec3& dim, const NxVec3& orientation);
	static void CreateWall(const NxVec3& pos, float brickSize, int length, int height, float angle, bool fillHoles);
	static void CreateTower(const NxVec3& pos, float brickSize, int wallLength, int wallHeight);

	static void DeleteNonEntityActor(NxActor* actor);

	static void PreTick();
	static void PostTick();
	static void Draw();
	static void DrawHud(GLenum mode);
	static void DrawPerfTestWindow();
	static void SimulateAndRender();

	static void ProcessKeyboardInput(unsigned char key, int x, int y);
	static void ProcessKeyboardSpecialInput(int key, int x, int y);
	static void ProcessMouseClick(int button, int state, int x, int y);
	static void ProcessMouseState(int x, int y);
	static void ProcessMouseMovement(int x, int y);
	static void ProcessMenuInput(int option);

	static inline Camera& GetCamera() { return camera; }
	static inline Light& GetSunLight() { return sunLight; }

	static NxVec3 CameraToWorldGridVector(const NxVec3& v);

	static void SetWind(const NxVec3& force);
	static inline const NxVec3& GetWind() { return wind; }

	static inline void SetCameraLocked(bool b) { cameraLocked = b; }
	static inline bool IsCameraLocked() { return cameraLocked; }

	static inline void SetObservedCannonBall(CannonBall* cannonBall) { observedCannonBall = cannonBall; }
	static inline CannonBall* GetObservedCannonBall() { return observedCannonBall; }

	static void HudMessage(const std::string& message);

	static void ToggleDebugRendering();
	static void ToggleGrass(bool message);
	static void ToggleFlag();
	static void ToggleCannonBallCamera();
	static void ToggleCameraLock();
};

#endif //PHYSICS_LOGIC_H
